#include <signal.h>

#include <vector>
#include <iostream>

#include <workflow/WFFacilities.h>
#include <workflow/WFHttpServer.h>
#include <workflow/HttpUtil.h>
#include <workflow/HttpMessage.h>
#include <workflow/RedisMessage.h>

using std::cout;
using std::endl;
using std::vector;
using std::string;

static WFFacilities::WaitGroup waitGroup(1);

void sighandler(int num)
{
    cout << "sighandler is processing" << endl;
    waitGroup.done();
}

struct SeriesContext
{
    string name;
    string password;
    protocol::HttpResponse * resp;
};

void httpCallback(WFHttpTask * serverTask)
{
    cout << "server httpCallback is running" << endl;
    auto context = (SeriesContext *)series_of(serverTask)->get_context();
    delete context;
    context = nullptr;
}

void redisCallback(WFRedisTask * );

void process(WFHttpTask * serverTask)
{
    cout << "\nprocess funciton is running\n";
    //0. 设置任务的回调函数
    serverTask->set_callback(httpCallback);
    //1. 解析请求
    //链接: http://192.168.30.128:8888/login?name=liubei&password=123
    auto req = serverTask->get_req();
    string uri = req->get_request_uri();
    // /login?name=liubei&password=123 
    cout << "uri:" << uri << endl;
    string nameKV = uri.substr(0, uri.find("&"));
    string passwordKV = uri.substr(uri.find("&") + 1);
    string name = nameKV.substr(nameKV.find("=") + 1);
    string password = passwordKV.substr(passwordKV.find("=") + 1);
    cout << "name:" << name << endl;
    cout << "password:" << password << endl;

    //2. 设置共享数据
    auto context = new SeriesContext;
    context->name = name;
    context->password = password;
    context->resp = serverTask->get_resp();
    series_of(serverTask)->set_context(context);

    //3. 创建redis任务
    string redisURL("redis://127.0.0.1:6379");
    auto redisTask = WFTaskFactory::create_redis_task(redisURL, 0, redisCallback);
    redisTask->get_req()->set_request("HGET", {"student", name});
    //4. 将redis任务放入序列中执行
    series_of(serverTask)->push_back(redisTask);
}

void test0()
{
    signal(SIGINT, sighandler);
    
    WFHttpServer server(process);

    if(server.start(8888) == 0) {
        waitGroup.wait();
        server.stop();
    } else {
        cout << "server cannot start" << endl;
    }
}


int main()
{
    test0();
    return 0;
}

void redisCallback(WFRedisTask * redisTask)
{
    cout << "redisCallback is running" << endl;
    //错误检测
    auto req = redisTask->get_req();
    auto resp = redisTask->get_resp();
    int state = redisTask->get_state();
    int error = redisTask->get_error();
    protocol::RedisValue result;//结果集
    switch(state){
    case  WFT_STATE_SYS_ERROR:
        printf("system error: %s\n", strerror(error));break;
    case  WFT_STATE_DNS_ERROR:
        printf("dns error: %s", gai_strerror(state)); break;
    case WFT_STATE_SUCCESS:
        resp->get_result(result);
        break;
    }
    if(state != WFT_STATE_SUCCESS) {
        printf("occurs error\n");
        return;
    }

    //接下来就是解析RedisRequest
    string command;
    vector<string> params;
    req->get_command(command);
    req->get_params(params);
    cout << "Request command：" << command << " ";
    for(auto & elem : params) {
        cout << elem << " ";
    }
    cout << endl;

    string strLoginSuccess("Login Success");
    string strLoginFail("Login Failed");
    //将数据与共享数据的进行比对
    auto context = (SeriesContext *)series_of(redisTask)->get_context();
    //解析响应信息RedisResponse.RedisValue
    if(result.is_string()) {
        cout << "Response is string:" << result.string_value() << endl;
        if(context->password == result.string_value()) {
            context->resp->append_output_body(strLoginSuccess.c_str(), strLoginSuccess.size());
            context->resp->add_header_pair("Content-Length", std::to_string(strLoginSuccess.size()));
        } else {
            context->resp->append_output_body(strLoginFail.c_str(), strLoginFail.size());
            context->resp->add_header_pair("Content-Length", std::to_string(strLoginFail.size()));
        }
    } else {
        context->resp->append_output_body(strLoginFail.c_str(), strLoginFail.size());
        context->resp->add_header_pair("Content-Length", std::to_string(strLoginFail.size()));
    }

    //设置响应报文的起始行
    context->resp->set_http_version("HTTP/1.1");
    context->resp->set_status_code("200");
    context->resp->set_reason_phrase("OK");
    //设置响应报文的首部字段
    context->resp->add_header_pair("Content-Type", "text/plain");
    context->resp->add_header_pair("Connection", "Keep-alive");
}

